package com.lucaswangdev.myswitch.core;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.lucaswangdev.myswitch.annotation.DynamicConfig;
import okhttp3.*;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 配置管理器，负责配置的加载、更新和管理
 */
public class ConfigManager {
    private static final ConfigManager INSTANCE = new ConfigManager();
    
    private final Map<String, Object> configCache = new ConcurrentHashMap<>();
    private final Map<Field, Object> dynamicFields = new ConcurrentHashMap<>();
    private final OkHttpClient httpClient = new OkHttpClient();
    private final Gson gson = new Gson();
    
    private String configServerUrl;
    private String appId;
    private String namespace;
    
    private ConfigManager() {}
    
    public static ConfigManager getInstance() {
        return INSTANCE;
    }
    
    /**
     * 初始化配置管理器
     * @param configServerUrl 配置中心地址
     * @param appId 应用ID
     * @param namespace 命名空间
     */
    public void init(String configServerUrl, String appId, String namespace) {
        System.out.println("Initializing ConfigManager with: " + configServerUrl + ", " + appId + ", " + namespace);
        this.configServerUrl = configServerUrl;
        this.appId = appId;
        this.namespace = namespace;
        
        // 初始化时加载配置
        loadConfig();
    }
    
    /**
     * 从配置中心加载配置
     */
    private void loadConfig() {
        try {
            String url = String.format("%s/config/%s/%s", configServerUrl, appId, namespace);
            System.out.println("Loading config from: " + url);
            Request request = new Request.Builder()
                    .url(url)
                    .build();
            
            try (Response response = httpClient.newCall(request).execute()) {
                System.out.println("Response code: " + response.code());
                if (response.isSuccessful() && response.body() != null) {
                    String responseBody = response.body().string();
                    System.out.println("Response body: " + responseBody);
                    Map<String, String> configMap = gson.fromJson(responseBody, 
                            new TypeToken<Map<String, String>>(){}.getType());
                    
                    // 更新本地缓存
                    configCache.clear();
                    for (Map.Entry<String, String> entry : configMap.entrySet()) {
                        System.out.println("Caching config: " + entry.getKey() + " = " + entry.getValue());
                        configCache.put(entry.getKey(), entry.getValue());
                    }
                } else {
                    System.out.println("Failed to load config, response not successful");
                }
            }
        } catch (IOException e) {
            System.out.println("Exception while loading config:");
            e.printStackTrace();
        }
    }
    
    /**
     * 获取配置项值
     * @param key 配置项键
     * @param defaultValue 默认值
     * @return 配置项值
     */
    public String getConfig(String key, String defaultValue) {
        return (String) configCache.getOrDefault(key, defaultValue);
    }
    
    /**
     * 注册需要动态更新的字段
     * @param bean 对象实例，如果是静态字段则为null
     * @param field 字段
     */
    public void registerDynamicField(Object bean, Field field) {
        System.out.println("Registering field: " + (field != null ? field.getName() : "null") + ", bean: " + bean);
        if (field == null) {
            System.out.println("Field is null!");
            return;
        }
        DynamicConfig annotation = field.getAnnotation(DynamicConfig.class);
        if (annotation != null) {
            System.out.println("Adding to dynamicFields: field=" + field + ", bean=" + bean);
            if (field == null) {
                System.out.println("Field is null before put!");
                return;
            }
            // 使用一个非null的占位符对象而不是null
            dynamicFields.put(field, bean != null ? bean : new Object());
            // 初始化字段值
            updateField(bean, field, annotation.key(), annotation.defaultValue());
        }
    }
    
    /**
     * 更新配置项
     * @param key 配置项键
     * @param value 配置项值
     */
    public void updateConfig(String key, String value) {
        configCache.put(key, value);
        // 更新所有注册的动态字段
        updateDynamicFields(key, value);
    }
    
    /**
     * 更新所有注册的动态字段
     * @param key 配置项键
     * @param value 配置项值
     */
    private void updateDynamicFields(String key, String value) {
        for (Map.Entry<Field, Object> entry : dynamicFields.entrySet()) {
            Field field = entry.getKey();
            Object bean = entry.getValue();
            
            DynamicConfig annotation = field.getAnnotation(DynamicConfig.class);
            if (annotation != null && annotation.key().equals(key)) {
                updateField(bean, field, key, value);
            }
        }
    }
    
    /**
     * 更新字段值
     * @param bean 对象实例，如果是静态字段则为null
     * @param field 字段
     * @param key 配置项键
     * @param value 配置项值
     */
    private void updateField(Object bean, Field field, String key, String value) {
        try {
            field.setAccessible(true);
            Class<?> fieldType = field.getType();
            
            // 对于静态字段，bean参数为null，我们直接传递null给field.set()
            // 对于实例字段，传递实际的bean对象
            Object target = bean;
            
            if (fieldType == String.class) {
                field.set(target, value);
            } else if (fieldType == int.class || fieldType == Integer.class) {
                field.set(target, Integer.parseInt(value));
            } else if (fieldType == boolean.class || fieldType == Boolean.class) {
                field.set(target, Boolean.parseBoolean(value));
            } else if (fieldType == long.class || fieldType == Long.class) {
                field.set(target, Long.parseLong(value));
            } else if (fieldType == double.class || fieldType == Double.class) {
                field.set(target, Double.parseDouble(value));
            } else {
                field.set(target, value);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }
}